<template>
  <ContentWrap>
    <!-- 搜索工作栏 -->
    <el-form
      class="-mb-15px"
      :model="queryParams"
      ref="queryFormRef"
      :inline="true"
      label-width="68px"
    >
      <el-form-item label="软件名称" prop="name">
        <el-input
          v-model="queryParams.name"
          placeholder="请输入软件名称"
          clearable
          @keyup.enter="handleQuery"
          class="!w-240px"
        />
      </el-form-item>
      <el-form-item label="软件类型" prop="type">
        <el-select
          v-model="queryParams.type"
          placeholder="请选择软件类型"
          clearable
          class="!w-240px"
        >
          <el-option
            v-for="dict in getStrDictOptions(DICT_TYPE.COMPO_MAIN_FRAMEWORK)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="作者" prop="author">
        <el-input
          v-model="queryParams.author"
          placeholder="请输入作者"
          clearable
          @keyup.enter="handleQuery"
          class="!w-240px"
        />
      </el-form-item>
      <el-form-item label="软件状态" prop="status">
        <el-select
          v-model="queryParams.status"
          placeholder="请选择软件状态"
          clearable
          class="!w-240px"
        >
          <el-option
            v-for="dict in getStrDictOptions(DICT_TYPE.COMPO_MAIN_STATUS)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="创建时间" prop="createTime">
        <el-date-picker
          v-model="queryParams.createTime"
          value-format="YYYY-MM-DD HH:mm:ss"
          type="daterange"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
          class="!w-220px"
        />
      </el-form-item>
      <el-form-item>
        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
        <el-button
          type="primary"
          plain
          @click="openForm('create')"
          v-hasPermi="['compo:base-info:create']"
        >
          <Icon icon="ep:plus" class="mr-5px" /> 新增
        </el-button>
        <el-button
          type="success"
          plain
          @click="handleExport"
          :loading="exportLoading"
          v-hasPermi="['compo:base-info:export']"
        >
          <Icon icon="ep:download" class="mr-5px" /> 导出
        </el-button>
      </el-form-item>
    </el-form>
  </ContentWrap>

  <!-- 列表 -->
  <ContentWrap>
    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
      <el-table-column label="编号" align="center" prop="id" />
      <el-table-column label="软件名称" align="center" prop="name" />

      <el-table-column label="软件类型" align="center" prop="type">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.COMPO_MAIN_FRAMEWORK" :value="scope.row.type" />
        </template>
      </el-table-column>
      <el-table-column label="作者" align="center" prop="author" />
      <el-table-column label="软件状态" align="center" prop="status">
        <template #default="scope">
          <dict-tag :type="DICT_TYPE.COMPO_MAIN_STATUS" :value="scope.row.status" />
        </template>
      </el-table-column>
      <el-table-column
        label="创建时间"
        align="center"
        prop="createTime"
        :formatter="dateFormatter"
        width="180px"
      />
      <el-table-column label="功能详情" align="center">
        <template #default="scope">
          <el-button
            v-if="scope.row.description"
            link
            type="primary"
            @click="showDescription(scope.row)"
          >
            查看详情
          </el-button>
          <span v-else>-</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" min-width="160px">
        <template #default="scope">
          <div class="table-operation-buttons">
            <div class="button-row">
              <el-button
                link
                type="primary"
                @click="handleViewReleaseHistory(scope.row.id, scope.row.name)"
              >
                发布日志
              </el-button>
              <el-button
                link
                type="primary"
                @click="handleAttachmentManage(scope.row.id, scope.row.name)"
              >
                附件管理
              </el-button>
              <el-button
                link
                type="primary"
                @click="handleViewDevInfo(scope.row.id, scope.row.name)"
              >
                开发信息
              </el-button>
            </div>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" min-width="160px">
        <template #default="scope">
          <div class="table-operation-buttons">
            <div class="button-row">
              <el-button
                link
                type="primary"
                @click="openForm('update', scope.row.id)"
                v-hasPermi="['compo:base-info:update']"
              >
                编辑
              </el-button>
              <el-button
                link
                type="danger"
                @click="handleDelete(scope.row.id)"
                v-hasPermi="['compo:base-info:delete']"
              >
                删除
              </el-button>
              <!-- <el-button link type="primary" @click="handleViewManual(scope.row.id)">
                <el-icon><icon-document /></el-icon> 查看操作手册
              </el-button> -->
            </div>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <Pagination
      :total="total"
      v-model:page="queryParams.pageNo"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />
  </ContentWrap>

  <!-- 表单弹窗：添加/修改 -->
  <BaseInfoForm ref="formRef" @success="getList" />

  <!-- 发布历史弹窗 -->
  <HistoryForm ref="historyFormRef" @success="getList" />

  <!-- 功能详情弹窗 -->
  <el-drawer
    v-model="descriptionVisible"
    title="功能详情"
    direction="btt"
    size="50%"
    :before-close="closeDescription"
    append-to-body
  >
    <div class="description-content" v-html="currentDescription"></div>
  </el-drawer>

  <!-- 发布历史抽屉 -->
  <el-drawer
    v-model="releaseHistoryVisible"
    :title="currentSoftwareName ? `${currentSoftwareName} - 发布历史` : '发布历史'"
    direction="rtl"
    size="50%"
    :before-close="closeReleaseHistory"
    append-to-body
  >
    <div class="release-history-content" v-loading="releaseHistoryLoading">
      <div class="history-header">
        <el-button type="primary" @click="handleAddHistory">
          <Icon icon="ep:plus" class="mr-5px" />添加版本记录
        </el-button>
      </div>
      <el-empty v-if="releaseHistoryList.length === 0" description="暂无发布历史" />
      <el-timeline v-else>
        <el-timeline-item
          v-for="(item, index) in releaseHistoryList"
          :key="index"
          :timestamp="formatReleaseDate(item.releaseDate)"
          placement="top"
          :type="getTimelineItemType(index)"
        >
          <el-card>
            <div class="history-card-header">
              <h4>版本: {{ item.version }}</h4>
              <div class="history-actions">
                <el-button link type="primary" @click="handleEditHistory(item)">
                  <Icon icon="ep:edit" />编辑
                </el-button>
                <el-button link type="danger" @click="handleDeleteHistory(item.id)">
                  <Icon icon="ep:delete" />删除
                </el-button>
              </div>
            </div>
            <p class="release-log">{{ item.releaseLog }}</p>
            <div class="history-card-footer">
              <div class="download-actions">
                <el-button
                  v-if="item.installUrl"
                  link
                  type="primary"
                  @click="handleDownloadHistoryPackage(item)"
                >
                  <el-icon><icon-download /></el-icon> 下载安装包
                </el-button>
                <el-button
                  v-if="item.docUrl"
                  link
                  type="primary"
                  @click="handleViewHistoryManual(item)"
                >
                  <el-icon><icon-document /></el-icon> 查看操作手册
                </el-button>
              </div>
            </div>
          </el-card>
        </el-timeline-item>
      </el-timeline>
    </div>
  </el-drawer>

  <!-- 发布历史表单弹窗 -->
  <el-dialog
    v-model="historyFormVisible"
    :title="historyFormType === 'create' ? '添加版本记录' : '编辑版本记录'"
    width="600px"
    append-to-body
  >
    <el-form
      ref="historyDialogFormRef"
      :model="historyForm"
      :rules="historyFormRules"
      label-width="100px"
      v-loading="historyFormLoading"
    >
      <el-form-item label="所属软件" prop="baseInfoId">
        <el-select
          v-model="historyForm.baseInfoId"
          placeholder="请选择所属软件"
          :disabled="!!historyForm.baseInfoId"
        >
          <el-option
            :key="currentSoftwareId"
            :label="currentSoftwareName"
            :value="currentSoftwareId"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="发布日期" prop="releaseDate">
        <el-date-picker
          :disabled="true"
          v-model="historyForm.releaseDate"
          type="datetime"
          format="YYYY-MM-DD HH:mm:ss"
          date-format="MMM DD, YYYY"
          time-format="HH:mm"
          placeholder="选择发布日期"
        />
      </el-form-item>
      <el-form-item label="版本" prop="version">
        <el-input v-model="historyForm.version" placeholder="请输入版本" />
      </el-form-item>

      <el-form-item label="发布日志" prop="releaseLog">
        <el-input
          v-model="historyForm.releaseLog"
          type="textarea"
          :rows="4"
          placeholder="请输入发布日志"
        />
      </el-form-item>
      <el-form-item label="安装包" prop="installUrl">
        <UploadFile
          v-model="historyForm.installUrl"
          :limit="1"
          :isShowTip="false"
          :fileSize="999"
          :fileType="['']"
          @update:modelValue="handleInstallFileChange"
        />
        <div class="el-upload__tip">只能上传1个安装包文件，不限制文件格式和大小</div>
      </el-form-item>
      <el-form-item label="操作手册" prop="docUrl">
        <UploadFile
          v-model="historyForm.docUrl"
          :limit="1"
          :fileSize="999"
          @update:modelValue="handleDocFileChange"
          :fileType="['pdf']"
        />
        <div class="el-upload__tip">只能上传1个PDF格式的操作手册文件</div>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="submitHistoryForm" type="primary" :loading="historyFormSubmitLoading"
        >确 定</el-button
      >
      <el-button @click="historyFormVisible = false">取 消</el-button>
    </template>
  </el-dialog>

  <!-- 附件管理抽屉 -->
  <el-drawer
    v-model="attachmentVisible"
    :title="currentSoftwareName ? `${currentSoftwareName} - 附件管理` : '附件管理'"
    direction="rtl"
    size="80%"
    :before-close="closeAttachment"
    append-to-body
  >
    <div class="attachment-container">
      <el-row :gutter="20">
        <!-- 左侧文件夹树 -->
        <el-col :span="6">
          <div class="folder-tree-container" v-loading="dirTreeLoading">
            <div class="folder-tree-header">
              <span>文件目录</span>
              <div class="folder-tree-actions">
                <el-button type="primary" size="small" @click="handleAddDir">
                  <Icon icon="ep:plus" class="mr-5px" />新增目录
                </el-button>
              </div>
            </div>
            <el-tree
              ref="dirTreeRef"
              :data="dirTreeData"
              node-key="id"
              :props="{ label: 'name', children: 'children' }"
              highlight-current
              default-expand-all
              @node-click="handleDirNodeClick"
            >
              <template #default="{ node, data }">
                <div class="custom-tree-node">
                  <span>{{ node.label }}</span>
                  <span v-if="data.id !== 0" class="node-actions">
                    <el-button link type="primary" size="small" @click.stop="handleEditDir(data)">
                      <Icon icon="ep:edit" />
                    </el-button>
                    <el-button link type="danger" size="small" @click.stop="handleDeleteDir(data)">
                      <Icon icon="ep:delete" />
                    </el-button>
                  </span>
                </div>
              </template>
            </el-tree>
            <el-empty v-if="dirTreeData.length === 0" description="暂无文件目录" />
          </div>
        </el-col>

        <!-- 右侧文件列表 -->
        <el-col :span="18">
          <div class="file-list-container" v-loading="fileListLoading">
            <div class="file-list-header">
              <span>{{ currentDirName ? currentDirName : '所有文件' }}</span>
              <div class="file-list-actions">
                <el-button type="primary" size="small" @click="handleAddAttachment">
                  <Icon icon="ep:plus" class="mr-5px" />新增附件
                </el-button>
              </div>
            </div>
            <el-table :data="fileList" :stripe="true" style="width: 100%">
              <el-table-column label="文件名" prop="fileName" min-width="200" />
              <el-table-column label="类型" prop="type" width="150">
                <template #default="scope">
                  <dict-tag :type="DICT_TYPE.COMPO_ATTACHMENT_TYPE" :value="scope.row.type" />
                </template>
              </el-table-column>
              <el-table-column
                label="上传时间"
                prop="createTime"
                width="180"
                :formatter="dateFormatter"
              />
              <el-table-column label="操作" align="center" width="200">
                <template #default="scope">
                  <el-button link type="primary" @click="downloadFile(scope.row)"> 下载 </el-button>
                  <el-button link type="info" @click="previewFile(scope.row)"> 预览 </el-button>
                  <el-button link type="danger" @click="handleDeleteAttachment(scope.row)">
                    删除
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
            <el-empty v-if="fileList.length === 0" description="暂无文件" />
          </div>
        </el-col>
      </el-row>
    </div>
  </el-drawer>

  <!-- 文件预览弹窗 -->
  <el-dialog v-model="previewDialogVisible" title="文件预览" width="90%" fullscreen>
    <div class="file-preview-container">
      <!-- 图片预览 -->
      <div v-if="fileType === 'image'" class="image-preview">
        <img :src="previewUrl" alt="图片预览" class="preview-image" />
      </div>

      <!-- PDF预览 -->
      <iframe
        v-else-if="fileType === 'pdf'"
        :src="pdfViewerUrl"
        class="file-preview-frame"
        sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-downloads allow-top-navigation"
      ></iframe>

      <!-- 文本预览 -->
      <div v-else-if="fileType === 'text'" class="text-preview">
        <pre v-if="textContent" class="text-content">{{ textContent }}</pre>
        <div v-else class="loading-text">加载文本内容中...</div>
      </div>

      <!-- Office文档预览 -->
      <div v-else-if="fileType === 'office'" class="office-preview">
        <iframe :src="officePreviewUrl" class="file-preview-frame"></iframe>
      </div>

      <!-- 不支持预览的文件类型 -->
      <el-empty v-else description="该文件类型不支持预览，请下载后查看" />
    </div>
    <template #footer>
      <div class="preview-footer">
        <div class="file-info" v-if="currentPreviewFile">
          <span class="file-name">{{ currentPreviewFile.fileName }}</span>
          <span class="file-type" v-if="currentPreviewFile.type">
            <dict-tag :type="DICT_TYPE.COMPO_ATTACHMENT_TYPE" :value="currentPreviewFile.type" />
          </span>
        </div>
        <div class="preview-actions">
          <el-button @click="previewDialogVisible = false">关闭</el-button>
          <el-button type="primary" @click="downloadCurrentFile">下载</el-button>
        </div>
      </div>
    </template>
  </el-dialog>

  <!-- 附件表单弹窗 -->
  <AttachmentForm ref="attachmentFormRef" @success="loadFileList" />

  <!-- 文件目录表单弹窗 -->
  <FileDirForm ref="dirFormRef" @success="loadDirTree" />

  <!-- 开发信息抽屉 -->
  <el-drawer
    v-model="devInfoVisible"
    :title="currentSoftwareName ? `${currentSoftwareName} - 开发信息` : '开发信息'"
    direction="rtl"
    size="50%"
    :before-close="closeDevInfo"
    append-to-body
  >
    <div class="dev-info-container" v-loading="devInfoLoading">
      <el-empty
        v-if="!devInfo || (!devInfo.gitUrl && !devInfo.downloadUrl && !devInfo.port)"
        description="暂无开发信息"
      />
      <el-descriptions v-else :column="1" border>
        <el-descriptions-item label="Git地址">
          <el-link v-if="devInfo.gitUrl" :href="devInfo.gitUrl" target="_blank" type="primary">
            {{ devInfo.gitUrl }}
          </el-link>
          <span v-else>-</span>
        </el-descriptions-item>
        <el-descriptions-item label="下载地址">
          <el-link
            v-if="devInfo.downloadUrl"
            :href="devInfo.downloadUrl"
            target="_blank"
            type="primary"
          >
            {{ devInfo.downloadUrl }}
          </el-link>
          <span v-else>-</span>
        </el-descriptions-item>
        <el-descriptions-item label="端口">
          {{ devInfo.port || '-' }}
        </el-descriptions-item>
      </el-descriptions>

      <!-- 编辑按钮 -->
      <div class="dev-info-actions">
        <el-button type="primary" @click="handleEditDevInfo">编辑开发信息</el-button>
      </div>
    </div>
  </el-drawer>

  <!-- 开发信息编辑弹窗 -->
  <el-dialog
    v-model="devInfoFormVisible"
    :title="currentSoftwareName ? `${currentSoftwareName} - 编辑开发信息` : '编辑开发信息'"
    width="600px"
  >
    <el-form
      ref="devInfoFormRef"
      :model="devInfoForm"
      :rules="devInfoFormRules"
      label-width="100px"
      v-loading="devInfoFormLoading"
    >
      <el-form-item label="Git地址" prop="gitUrl">
        <el-input v-model="devInfoForm.gitUrl" placeholder="请输入Git地址" />
      </el-form-item>
      <el-form-item label="下载地址" prop="downloadUrl">
        <el-input v-model="devInfoForm.downloadUrl" placeholder="请输入下载地址" />
      </el-form-item>
      <el-form-item label="端口" prop="port">
        <el-input v-model="devInfoForm.port" placeholder="请输入端口" />
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="devInfoFormVisible = false">取消</el-button>
      <el-button type="primary" @click="submitDevInfo" :loading="devInfoSubmitLoading">
        确定
      </el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
import { dateFormatter } from '@/utils/formatTime'
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
import download from '@/utils/download'
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
import { BaseInfoApi, BaseInfoVO } from '@/api/compo/compoBaseInfo'
import { AttachmentApi, AttachmentVO } from '@/api/compo/compoAttachment'
import { FileDirApi, FileDirVO } from '@/api/compo/compoFileDir'
import { HistoryApi, HistoryVO } from '@/api/compo/compoHistory'
import { DevelopApi, DevelopVO } from '@/api/compo/compoDevelop'
/* @ts-ignore */
import BaseInfoForm from './BaseInfoForm.vue'
/* @ts-ignore */
import HistoryForm from '@/views/compo/compoHistory/HistoryForm.vue'
/* @ts-ignore */
import AttachmentForm from '@/views/compo/compoAttachment/AttachmentForm.vue'
/* @ts-ignore */
import FileDirForm from '@/views/compo/compoFileDir/FileDirForm.vue'
import { ElMessage, ElLoading } from 'element-plus'
// @ts-ignore
import {
  ArrowDown as IconArrowDown,
  Download as IconDownload,
  Document as IconDocument,
  Upload as IconUpload,
  Tickets as IconTickets,
  Folder as IconFolder,
  Delete as IconDelete,
  EditPen as IconEditPen
} from '@element-plus/icons-vue'
import dayjs from 'dayjs'

/** 软件信息 列表 */
defineOptions({ name: 'CompoBaseInfo' })

const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const fileTypeSet = ref([])
const loading = ref(true) // 列表的加载中
const list = ref<BaseInfoVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  name: undefined,
  description: undefined,
  type: undefined,
  author: undefined,
  status: undefined,
  createTime: []
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中

// 功能详情弹窗相关
const descriptionVisible = ref(false)
const currentDescription = ref('')

// 发布历史抽屉相关
const releaseHistoryVisible = ref(false)
const releaseHistoryLoading = ref(false)
const releaseHistoryList = ref([])
const releaseHistoryTotal = ref(0)
const currentSoftwareName = ref('')
const currentSoftwareId = ref<number | null>(null)
const releaseHistoryQuery = reactive({
  pageNo: 1,
  pageSize: 100,
  baseInfoId: undefined as number | undefined
})

// 发布历史表单相关
const historyFormVisible = ref(false)
const historyFormLoading = ref(false)
const historyFormSubmitLoading = ref(false)
const historyFormType = ref<'create' | 'update'>('create')
const historyForm = ref<{
  id?: number
  baseInfoId: number | undefined
  version?: string
  releaseDate?: string
  releaseLog?: string
  installUrl?: string
  docUrl?: string
}>({
  id: undefined,
  baseInfoId: undefined,
  version: undefined,
  releaseDate: undefined,
  releaseLog: undefined,
  installUrl: undefined,
  docUrl: undefined
})
const historyFormRules = reactive({
  baseInfoId: [{ required: true, message: '所属软件不能为空', trigger: 'change' }],
  version: [{ required: true, message: '版本不能为空', trigger: 'blur' }],
  releaseDate: [{ required: true, message: '发布日期不能为空', trigger: 'blur' }],
  releaseLog: [{ required: true, message: '发布日志不能为空', trigger: 'blur' }]
})
const historyDialogFormRef = ref()

// 附件管理抽屉相关
const attachmentVisible = ref(false)
const dirTreeLoading = ref(false)
const fileListLoading = ref(false)
const dirTreeData = ref<any[]>([])
const fileList = ref<AttachmentVO[]>([])
const currentDirId = ref<number | null>(null)
const currentDirName = ref('')
const dirTreeRef = ref()
const attachmentFormRef = ref()
const dirFormRef = ref()

// 文件预览相关
const previewDialogVisible = ref(false)
const previewUrl = ref('')
const pdfViewerUrl = ref('')
const currentPreviewFile = ref<AttachmentVO | null>(null)
const fileType = ref<'image' | 'pdf' | 'text' | 'office' | 'other'>('other')
const textContent = ref<string>('')
const officePreviewUrl = ref<string>('')
const usePdfViewer = ref<'native' | 'pdfjs'>('pdfjs') // 默认使用PDF.js预览

// 开发信息相关
const devInfoVisible = ref(false)
const devInfoLoading = ref(false)
const devInfo = ref<any | null>(null)
const devInfoFormVisible = ref(false)
const devInfoForm = ref<{
  id?: number
  baseInfoId: number
  gitUrl?: string
  downloadUrl?: string
  port?: string | number
}>({
  id: undefined,
  baseInfoId: 0, // 初始值设为0，后续会被正确设置
  gitUrl: undefined,
  downloadUrl: undefined,
  port: undefined
})
const devInfoFormRules = reactive({
  gitUrl: [{ required: true, message: 'Git地址不能为空', trigger: 'blur' }],
  downloadUrl: [{ required: true, message: '下载地址不能为空', trigger: 'blur' }]
})
const devInfoFormRef = ref()
const devInfoFormLoading = ref(false)
const devInfoSubmitLoading = ref(false)

/** 软件信息 列表 */
const getList = async () => {
  loading.value = true
  try {
    const data = await BaseInfoApi.getBaseInfoPage(queryParams)
    list.value = data.list
    total.value = data.total
  } finally {
    loading.value = false
  }
}

/** 搜索按钮操作 */
const handleQuery = () => {
  queryParams.pageNo = 1
  getList()
}

/** 重置按钮操作 */
const resetQuery = () => {
  queryFormRef.value.resetFields()
  handleQuery()
}

/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
  formRef.value.open(type, id)
}

/** 发布版本操作 */
const historyFormRef = ref()
const handleRelease = (id: number) => {
  historyFormRef.value.open('create', undefined, id)
}

/** 查看发布历史 */
const handleViewReleaseHistory = (id: number, name: string) => {
  currentSoftwareId.value = id
  currentSoftwareName.value = name || '未知软件'
  releaseHistoryQuery.baseInfoId = id
  releaseHistoryVisible.value = true
  getReleaseHistoryList()
}

/** 获取发布历史列表 */
const getReleaseHistoryList = async () => {
  if (!releaseHistoryQuery.baseInfoId) return
  releaseHistoryLoading.value = true
  try {
    const data = await HistoryApi.getHistoryPage(releaseHistoryQuery)
    releaseHistoryList.value = data.list || []
    releaseHistoryTotal.value = data.total || 0
  } catch (error) {
    console.error('获取发布历史失败', error)
    message.error('获取发布历史失败')
  } finally {
    releaseHistoryLoading.value = false
  }
}

/** 关闭发布历史抽屉 */
const closeReleaseHistory = () => {
  releaseHistoryVisible.value = false
  currentSoftwareName.value = ''
  currentSoftwareId.value = null
  releaseHistoryList.value = []
}

/** 格式化发布日期 */
const formatReleaseDate = (timestamp: number | string) => {
  if (!timestamp) return '未知时间'

  // 判断是时间戳还是字符串格式
  if (typeof timestamp === 'number') {
    // 如果是时间戳，需要判断是毫秒还是秒
    const date = timestamp > 9999999999 ? timestamp : timestamp * 1000
    return dayjs(date).format('YYYY-MM-DD')
  } else {
    // 如果已经是字符串，尝试格式化
    return dayjs(timestamp).format('YYYY-MM-DD')
  }
}

/** 获取时间线项类型 */
const getTimelineItemType = (index: number) => {
  const types = ['primary', 'success', 'warning', 'danger']
  return types[index % types.length]
}

/** 删除按钮操作 */
const handleDelete = async (id: number) => {
  try {
    // 删除的二次确认
    await message.delConfirm()
    // 发起删除
    await BaseInfoApi.deleteBaseInfo(id)
    message.success(t('common.delSuccess'))
    // 刷新列表
    await getList()
  } catch {}
}

/** 导出按钮操作 */
const handleExport = async () => {
  try {
    // 导出的二次确认
    await message.exportConfirm()
    // 发起导出
    exportLoading.value = true
    const data = await BaseInfoApi.exportBaseInfo(queryParams)
    download.excel(data, '软件信息.xls')
  } catch {
  } finally {
    exportLoading.value = false
  }
}

/** 查看操作手册 */
const handleViewManual = async (id: number) => {
  try {
    const manuals = await HistoryApi.getLatest(id)
    if (!manuals || !manuals.docUrl) {
      message.warning('未找到该软件的操作手册')
      return
    }

    // 使用第一个找到的操作手册
    const manualFile = manuals

    // 获取文件路径
    const filePath = manualFile.docUrl
    const previewUrl =
      filePath.startsWith('http://') || filePath.startsWith('https://')
        ? filePath // 如果是完整URL，直接使用
        : import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + filePath // 如果是相对路径，拼接baseUrl

    // 判断文件类型，如果是PDF直接打开，否则下载
    const fileExt = filePath.split('.').pop()?.toLowerCase() || ''

    if (fileExt === 'pdf') {
      // PDF文件直接在新窗口打开预览
      window.open(previewUrl, '_blank')
    } else {
      // 非PDF文件，使用下载方式处理
      const loading = ElLoading.service({
        lock: true,
        text: '文件下载中...',
        background: 'rgba(0, 0, 0, 0.7)'
      })

      try {
        // 使用fetch API下载文件
        const response = await fetch(previewUrl)
        if (!response.ok) {
          throw new Error('下载失败，服务器响应错误')
        }

        const blob = await response.blob()
        // 创建一个临时URL
        const url = window.URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.href = url
        a.download = manualFile.fileName || '操作手册.pdf'
        document.body.appendChild(a)
        a.click()
        window.URL.revokeObjectURL(url)
        document.body.removeChild(a)
        message.success('下载成功')
      } catch (error) {
        console.error('下载操作手册失败:', error)
        message.error('下载操作手册失败')
      } finally {
        // 关闭加载提示
        loading.close()
      }
    }
  } catch (error) {
    console.error('获取操作手册失败:', error)
    message.error('获取操作手册失败')
  }
}

/** 附件管理 */
const handleAttachmentManage = async (id: number, name: string) => {
  currentSoftwareId.value = id
  currentSoftwareName.value = name || '未知软件'
  attachmentVisible.value = true

  // 加载文件目录树
  await loadDirTree()

  // 默认加载所有文件
  await loadFileList()
}

/** 新增文件目录 */
const handleAddDir = () => {
  dirFormRef.value.open('create')
}

/** 编辑文件目录 */
const handleEditDir = (data: FileDirVO) => {
  dirFormRef.value.open('update', data.id)
}

/** 删除文件目录 */
const handleDeleteDir = async (data: FileDirVO) => {
  try {
    // 确认是否删除
    await message.delConfirm('确定要删除该目录吗？删除后该目录下的文件将无法访问！')

    // 发起删除请求
    await FileDirApi.deleteFileDir(data.id)

    // 显示成功消息
    message.success('删除成功')

    // 重新加载目录树
    await loadDirTree()

    // 如果删除的是当前选中的目录，重置当前目录ID和名称
    if (currentDirId.value === data.id) {
      currentDirId.value = null
      currentDirName.value = ''
      await loadFileList() // 重新加载文件列表
    }
  } catch (error) {
    console.error('删除目录失败:', error)
  }
}

/** 新增附件 */
const handleAddAttachment = () => {
  // 先确保有软件ID
  if (!currentSoftwareId.value) {
    message.warning('请先选择软件')
    return
  }

  // 直接在open方法中传入软件ID和文件夹ID(如果有)
  attachmentFormRef.value.open(
    'create',
    undefined,
    currentSoftwareId.value,
    currentDirId.value || undefined
  )
}

/** 删除附件 */
const handleDeleteAttachment = async (row: AttachmentVO) => {
  try {
    await message.delConfirm()
    await AttachmentApi.deleteAttachment(row.id)
    message.success(t('common.delSuccess'))
    // 重新加载文件列表
    await loadFileList()
  } catch (error) {
    console.error('删除附件失败:', error)
  }
}

/** 加载文件目录树 */
const loadDirTree = async () => {
  dirTreeLoading.value = true
  try {
    const data = await FileDirApi.getFileDirList({})

    // 将平面数据转换为树形结构
    const tree = buildDirTree(data)
    dirTreeData.value = tree
  } catch (error) {
    console.error('获取文件目录失败:', error)
    message.error('获取文件目录失败')
  } finally {
    dirTreeLoading.value = false
  }
}

/** 构建目录树 */
const buildDirTree = (data: FileDirVO[]) => {
  const tree: any[] = []
  const map: Record<number, any> = {}

  // 先将所有节点放入map
  data.forEach((item) => {
    map[item.id] = {
      ...item,
      children: []
    }
  })

  // 构建树
  data.forEach((item) => {
    const node = map[item.id]
    if (item.preId === 0 || !map[item.preId]) {
      // 根节点或父节点不存在的情况
      tree.push(node)
    } else {
      // 将当前节点添加到父节点的children中
      map[item.preId].children.push(node)
    }
  })

  return tree
}

/** 处理目录树节点点击 */
const handleDirNodeClick = (data: any) => {
  currentDirId.value = data.id
  currentDirName.value = data.name
  loadFileList()
}

/** 加载文件列表 */
const loadFileList = async () => {
  if (!currentSoftwareId.value) return

  fileListLoading.value = true
  try {
    const params: any = {
      baseInfoId: currentSoftwareId.value
    }

    // 如果选择了目录，则按目录筛选
    if (currentDirId.value) {
      params.dirId = currentDirId.value
    }

    const data = await AttachmentApi.getAttachmentPage(params)
    fileList.value = data.list || []
  } catch (error) {
    console.error('获取文件列表失败:', error)
    message.error('获取文件列表失败')
  } finally {
    fileListLoading.value = false
  }
}

/** 预览文件 */
const previewFile = async (file: AttachmentVO) => {
  currentPreviewFile.value = file

  // 根据文件扩展名确定文件类型
  const fileName = file.fileName || ''
  const fileExt = fileName.split('.').pop()?.toLowerCase() || ''
  const baseUrl = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL

  // 判断文件路径是否为完整URL
  let filePath = file.filePath
  // 检查是否为外部URL（以http://或https://开头）
  if (filePath.startsWith('http://') || filePath.startsWith('https://')) {
    // 如果是完整URL，直接使用
    previewUrl.value = filePath
  } else {
    // 如果是相对路径，拼接baseUrl
    previewUrl.value = baseUrl + filePath
  }

  // 根据文件类型处理预览
  if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(fileExt)) {
    // 图片文件直接使用img标签预览
    fileType.value = 'image'
    previewDialogVisible.value = true

    // 显示加载中
    const loading = ElLoading.service({
      lock: true,
      text: '图片加载中...',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    // 预加载图片，确保图片加载完成后关闭加载提示
    const img = new Image()
    img.src = previewUrl.value
    img.onload = () => {
      loading.close()
    }
    img.onerror = () => {
      loading.close()
      message.error('图片加载失败')
    }

    // 设置超时处理，避免图片加载过慢
    setTimeout(() => {
      loading.close()
    }, 5000)
  } else if (fileExt === 'pdf') {
    // PDF文件使用PDF.js预览
    fileType.value = 'pdf'

    // 显示加载中
    const loading = ElLoading.service({
      lock: true,
      text: 'PDF加载中...',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    try {
      pdfViewerUrl.value = `https://mozilla.github.io/pdf.js/web/viewer.html?file=${encodeURIComponent(
        previewUrl.value
      )}`
      previewDialogVisible.value = true

      // 由于iframe加载无法直接监听，设置一个适当的超时时间后关闭loading
      setTimeout(() => {
        loading.close()
      }, 3000)
    } catch (error) {
      loading.close()
      message.error('PDF预览加载失败')
      console.error('PDF预览加载失败:', error)
    }
  } else if (['txt', 'log', 'md', 'json', 'xml', 'html', 'css', 'js'].includes(fileExt)) {
    // 文本文件需要获取内容后预览
    fileType.value = 'text'
    textContent.value = '' // 清空之前的内容
    previewDialogVisible.value = true

    // 显示加载中
    const loading = ElLoading.service({
      lock: true,
      text: '加载文本内容中...',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    try {
      // 获取文本内容
      const response = await fetch(previewUrl.value)
      if (response.ok) {
        textContent.value = await response.text()
      } else {
        message.error(`无法加载文本内容: ${response.status} ${response.statusText}`)
      }
    } catch (error) {
      message.error('获取文本内容失败')
      console.error('获取文本内容失败:', error)
    } finally {
      loading.close()
    }
  } else if (['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'].includes(fileExt)) {
    // Office文档使用在线预览服务
    fileType.value = 'office'

    // 显示加载中
    const loading = ElLoading.service({
      lock: true,
      text: 'Office文档加载中...',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    try {
      // 构建Office Online预览URL
      const officeOnlineUrl = 'https://view.officeapps.live.com/op/view.aspx?src='
      officePreviewUrl.value = officeOnlineUrl + encodeURIComponent(previewUrl.value)
      previewDialogVisible.value = true

      // 由于iframe加载无法直接监听，设置一个适当的超时时间后关闭loading
      setTimeout(() => {
        loading.close()
      }, 5000)
    } catch (error) {
      loading.close()
      message.error('Office文档预览加载失败')
      console.error('Office文档预览加载失败:', error)
    }
  } else {
    // 不支持预览的文件类型
    fileType.value = 'other'
    message.warning('该文件类型不支持在线预览，将为您下载该文件')
    downloadFile(file)
  }
}

/** 下载当前预览的文件 */
const downloadCurrentFile = () => {
  if (currentPreviewFile.value) {
    downloadFile(currentPreviewFile.value)
  } else {
    message.warning('没有可下载的文件')
  }
}

/** 下载文件 */
const downloadFile = async (file: AttachmentVO) => {
  try {
    const filePath = file.filePath
    if (!filePath) {
      message.error('文件路径不存在')
      return
    }

    const downloadUrl =
      filePath.startsWith('http://') || filePath.startsWith('https://')
        ? filePath // 如果是完整URL，直接使用
        : import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + filePath // 如果是相对路径，拼接baseUrl

    // 显示加载中
    const loading = ElLoading.service({
      lock: true,
      text: '文件下载中...',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    // 使用fetch API下载文件
    fetch(downloadUrl)
      .then((response) => {
        if (!response.ok) {
          throw new Error(`下载失败，服务器响应错误: ${response.status} ${response.statusText}`)
        }
        return response.blob()
      })
      .then((blob) => {
        // 创建一个临时URL
        const url = window.URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.href = url
        a.download = file.fileName || '未命名文件'
        document.body.appendChild(a)
        a.click()
        window.URL.revokeObjectURL(url)
        document.body.removeChild(a)
        message.success('下载成功')
      })
      .catch((error) => {
        console.error('下载文件失败:', error)
        message.error(`下载文件失败: ${error.message || '未知错误'}`)
      })
      .finally(() => {
        // 关闭加载提示
        loading.close()
      })
  } catch (error) {
    console.error('下载文件失败:', error)
    message.error(`下载文件失败: ${error instanceof Error ? error.message : '未知错误'}`)
  }
}

/** 关闭附件管理抽屉 */
const closeAttachment = () => {
  attachmentVisible.value = false
  currentDirId.value = null
  currentDirName.value = ''
  fileList.value = []
  dirTreeData.value = []
}

/** 切换PDF预览器 */
const togglePdfViewer = () => {
  // 切换预览模式
  usePdfViewer.value = usePdfViewer.value === 'pdfjs' ? 'native' : 'pdfjs'

  // 如果当前正在预览PDF文件，则重新加载预览
  if (fileType.value === 'pdf' && currentPreviewFile.value) {
    // 显示加载中
    const loading = ElLoading.service({
      lock: true,
      text: '切换预览模式...',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    try {
      if (usePdfViewer.value === 'pdfjs') {
        // 使用PDF.js预览
        pdfViewerUrl.value = `https://mozilla.github.io/pdf.js/web/viewer.html?file=${encodeURIComponent(
          previewUrl.value
        )}`
      } else {
        // 使用浏览器原生预览
        pdfViewerUrl.value = ''
      }
    } finally {
      loading.close()
    }
  }
}

/** 在新标签页打开PDF */
const handleOpenInNewTab = () => {
  if (pdfViewerUrl.value) {
    window.open(pdfViewerUrl.value, '_blank')
  } else if (previewUrl.value) {
    window.open(previewUrl.value, '_blank')
  }
}

/** 显示功能详情 */
const showDescription = (row: BaseInfoVO) => {
  currentDescription.value = row.description || ''
  descriptionVisible.value = true
}

/** 关闭功能详情弹窗 */
const closeDescription = () => {
  descriptionVisible.value = false
  currentDescription.value = ''
}

/** 查看开发信息 */
const handleViewDevInfo = (id: number, name: string) => {
  currentSoftwareId.value = id
  currentSoftwareName.value = name || '未知软件'
  devInfoVisible.value = true
  // 获取开发信息
  getDevInfo()
}

/** 获取开发信息 */
const getDevInfo = async () => {
  if (!currentSoftwareId.value) return

  devInfoLoading.value = true
  try {
    // 根据baseInfoId获取开发信息
    const data = await DevelopApi.getDevelopByBaseInfoId(currentSoftwareId.value)
    if (data) {
      // 数据存在，使用API返回的数据
      devInfo.value = data
      message.success('获取开发信息成功')
    } else {
      // 如果没有数据，返回空对象，准备创建新数据
      devInfo.value = {
        id: undefined,
        baseInfoId: currentSoftwareId.value,
        gitUrl: '',
        downloadUrl: '',
        port: ''
      }
      message.info('该软件暂无开发信息，可以点击编辑按钮添加')
    }
  } catch (error) {
    console.error('获取开发信息失败:', error)
    message.error('获取开发信息失败')
    // 错误时也设置空对象
    devInfo.value = {
      id: undefined,
      baseInfoId: currentSoftwareId.value,
      gitUrl: '',
      downloadUrl: '',
      port: ''
    }
  } finally {
    devInfoLoading.value = false
  }
}

/** 编辑开发信息 */
const handleEditDevInfo = () => {
  // 复制当前开发信息到表单
  devInfoForm.value = {
    ...devInfo.value,
    // 确保设置正确的软件ID
    baseInfoId: currentSoftwareId.value as number
  }
  devInfoFormVisible.value = true
}

/** 提交开发信息 */
const submitDevInfo = async () => {
  // 校验表单
  await devInfoFormRef.value.validate()

  devInfoSubmitLoading.value = true
  try {
    // 判断是新增还是更新
    if (devInfoForm.value.id) {
      // 已有ID，执行更新
      await DevelopApi.updateDevelop(devInfoForm.value as unknown as DevelopVO)
      message.success('更新开发信息成功')
    } else {
      // 没有ID，执行创建或更新
      await DevelopApi.createOrUpdateDevelop(devInfoForm.value as unknown as DevelopVO)
      message.success('添加开发信息成功')
    }

    // 重新获取开发信息以确保展示最新数据
    await getDevInfo()

    devInfoFormVisible.value = false
  } catch (error) {
    console.error('更新开发信息失败:', error)
    message.error('更新开发信息失败')
  } finally {
    devInfoSubmitLoading.value = false
  }
}

/** 关闭开发信息抽屉 */
const closeDevInfo = () => {
  devInfoVisible.value = false
  devInfo.value = null
}

/** 添加版本记录 */
const handleAddHistory = () => {
  historyFormType.value = 'create'
  resetHistoryForm()
  // 设置默认值
  historyForm.value.baseInfoId = currentSoftwareId.value || undefined
  // 设置当前日期时间为默认值，格式为 YYYY-MM-DD HH:mm:ss
  historyForm.value.releaseDate = dayjs().format('YYYY-MM-DD HH:mm:ss')
  historyFormVisible.value = true
}

/** 编辑版本记录 */
const handleEditHistory = (item: any) => {
  historyFormType.value = 'update'
  resetHistoryForm()
  // 填充表单数据
  historyForm.value = {
    id: item.id,
    baseInfoId: item.baseInfoId,
    version: item.version,
    releaseDate: item.releaseDate,
    releaseLog: item.releaseLog,
    installUrl: item.installUrl,
    docUrl: item.docUrl
  }
  historyFormVisible.value = true
}

/** 删除版本记录 */
const handleDeleteHistory = async (id: number) => {
  try {
    // 删除的二次确认
    await message.delConfirm('确定要删除该版本记录吗？')
    // 发起删除
    await HistoryApi.deleteHistory(id)
    message.success(t('common.delSuccess'))
    // 刷新列表
    await getReleaseHistoryList()
  } catch (error) {
    console.error('删除版本记录失败:', error)
  }
}

/** 提交发布历史表单 */
const submitHistoryForm = async () => {
  // 验证表单
  await historyDialogFormRef.value.validate()

  historyFormSubmitLoading.value = true
  try {
    const data = {
      id: historyForm.value.id,
      baseInfoId: historyForm.value.baseInfoId,
      version: historyForm.value.version,
      releaseDate: historyForm.value.releaseDate,
      releaseLog: historyForm.value.releaseLog,
      installUrl: historyForm.value.installUrl,
      docUrl: historyForm.value.docUrl
    } as unknown as HistoryVO

    if (historyFormType.value === 'create') {
      // 新增
      await HistoryApi.createHistory(data)
      message.success('添加版本记录成功')
    } else {
      // 修改
      await HistoryApi.updateHistory(data)
      message.success('编辑版本记录成功')
    }

    // 关闭表单并刷新列表
    historyFormVisible.value = false
    await getReleaseHistoryList()
  } catch (error) {
    console.error('提交版本记录失败:', error)
    message.error('提交版本记录失败')
  } finally {
    historyFormSubmitLoading.value = false
  }
}

/** 重置版本记录表单 */
const resetHistoryForm = () => {
  historyForm.value = {
    id: undefined,
    baseInfoId: undefined,
    version: undefined,
    releaseDate: undefined,
    releaseLog: undefined,
    installUrl: undefined,
    docUrl: undefined
  }
  historyDialogFormRef.value?.resetFields()
}

/** 处理安装包文件上传变化 */
const handleInstallFileChange = (newFilePath: string) => {
  if (!newFilePath) return

  console.log('安装包文件路径更新:', newFilePath)
  // 安装包不限制文件格式和大小
}

/** 处理操作手册文件上传变化 */
const handleDocFileChange = (newFilePath: string) => {
  if (!newFilePath) return

  console.log('操作手册文件路径更新:', newFilePath)

  // 获取文件扩展名并验证是否为PDF
  let fileExt = ''
  if (newFilePath.includes('/')) {
    const fileName = newFilePath.substring(newFilePath.lastIndexOf('/') + 1)
    if (fileName.includes('.')) {
      fileExt = fileName.split('.').pop()?.toLowerCase() || ''
    }
  }

  if (fileExt && fileExt !== 'pdf') {
    message.warning('操作手册只能上传PDF格式文件')
    historyForm.value.docUrl = '' // 清空非PDF文件
    return
  }
}

/** 下载历史版本安装包 */
const handleDownloadHistoryPackage = async (item: any) => {
  if (!item.installUrl) {
    message.warning('未找到该版本的安装包')
    return
  }

  // 显示加载中
  const loading = ElLoading.service({
    lock: true,
    text: '安装包下载中...',
    background: 'rgba(0, 0, 0, 0.7)'
  })

  try {
    // 获取文件路径
    const filePath = item.installUrl
    const fileUrl =
      filePath.startsWith('http://') || filePath.startsWith('https://')
        ? filePath // 如果是完整URL，直接使用
        : import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + filePath // 如果是相对路径，拼接baseUrl

    // 获取文件名
    let fileName = '安装包.exe'
    if (filePath.includes('/')) {
      fileName = filePath.substring(filePath.lastIndexOf('/') + 1)
    }
    // 解码文件名
    try {
      fileName = decodeURIComponent(fileName)
    } catch (e) {
      console.error('解码文件名失败:', e)
    }

    // 使用fetch API下载文件
    const response = await fetch(fileUrl)
    if (!response.ok) {
      throw new Error('下载失败，服务器响应错误')
    }

    const blob = await response.blob()
    // 创建一个临时URL
    const url = window.URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = fileName
    document.body.appendChild(a)
    a.click()
    window.URL.revokeObjectURL(url)
    document.body.removeChild(a)
    message.success('下载成功')
  } catch (error) {
    console.error('下载安装包失败:', error)
    message.error('下载安装包失败')
  } finally {
    // 关闭加载提示
    loading.close()
  }
}

/** 查看历史版本操作手册 */
const handleViewHistoryManual = async (item: any) => {
  if (!item.docUrl) {
    message.warning('未找到该版本的操作手册')
    return
  }

  // 获取文件路径
  const filePath = item.docUrl
  const docUrl =
    filePath.startsWith('http://') || filePath.startsWith('https://')
      ? filePath // 如果是完整URL，直接使用
      : import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + filePath // 如果是相对路径，拼接baseUrl

  // 获取文件名来判断文件类型
  let fileName = 'document.pdf'
  if (filePath.includes('/')) {
    fileName = filePath.substring(filePath.lastIndexOf('/') + 1)
  }
  // 解码文件名
  try {
    fileName = decodeURIComponent(fileName)
  } catch (e) {
    console.error('解码文件名失败:', e)
  }

  // 获取文件扩展名
  const fileExt = fileName.split('.').pop()?.toLowerCase() || ''

  if (fileExt === 'pdf') {
    // PDF文件，在新窗口打开

    window.open(filePath, '_blank')
  } else {
    // 其他类型文件，直接下载（理论上不会发生，因为我们限制了只能上传PDF）
    const loading = ElLoading.service({
      lock: true,
      text: '文件下载中...',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    try {
      // 使用fetch API下载文件
      const response = await fetch(docUrl)
      if (!response.ok) {
        throw new Error('下载失败，服务器响应错误')
      }

      const blob = await response.blob()
      // 创建一个临时URL
      const url = window.URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = fileName
      document.body.appendChild(a)
      a.click()
      window.URL.revokeObjectURL(url)
      document.body.removeChild(a)
      message.success('下载成功')
    } catch (error) {
      console.error('下载操作手册失败:', error)
      message.error('下载操作手册失败')
    } finally {
      loading.close()
    }
  }
}

/** 初始化 **/
onMounted(() => {
  getList()
})
</script>

<style scoped>
.description-content {
  max-height: 100vh;
  min-width: 100vw;

  overflow-y: auto;
  padding: 10px;
  line-height: 1.6;
  white-space: pre-wrap;
}

.release-history-content {
  padding: 20px;
  max-height: 100vh;
  overflow-y: auto;
}

.release-history-content .el-timeline {
  margin-bottom: 20px;
}

.release-history-content .el-timeline-item {
  margin-bottom: 20px;
}

.release-history-content .el-card {
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  transition: all 0.3s;
}

.release-history-content .el-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}

.history-header {
  margin-bottom: 20px;
  text-align: right;
}

.history-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.history-card-header h4 {
  margin: 0;
  font-size: 16px;
  font-weight: bold;
}

.history-actions {
  display: flex;
  gap: 5px;
}

.release-log {
  margin: 0;
  font-size: 14px;
  color: #606266;
  white-space: pre-wrap;
  line-height: 1.6;
}

.pagination-container {
  margin-top: 20px;
  text-align: right;
  padding-right: 20px;
}

.attachment-container {
  padding: 20px;
}

.folder-tree-container {
  background-color: #fff;
  padding: 10px;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.folder-tree-header {
  margin-bottom: 10px;
  font-size: 14px;
  font-weight: bold;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.folder-tree-actions {
  display: flex;
  gap: 10px;
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-right: 8px;
  width: 100%;
}

.node-actions {
  margin-left: 8px;
  opacity: 0;
  transition: opacity 0.2s;
}

.custom-tree-node:hover .node-actions {
  opacity: 1;
}

.file-list-container {
  background-color: #fff;
  padding: 10px;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.file-list-header {
  margin-bottom: 10px;
  font-size: 14px;
  font-weight: bold;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.file-list-actions {
  display: flex;
  gap: 10px;
}

/* 文件预览相关样式 */
.file-preview-container {
  width: 100%;
  height: 70vh;
  overflow: auto;
}

.preview-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.file-info {
  display: flex;
  align-items: center;
  gap: 10px;
}

.file-name {
  font-weight: bold;
  font-size: 16px;
  color: #303133;
}

.file-type {
  margin-left: 10px;
}

.preview-actions {
  display: flex;
  gap: 10px;
}

.file-preview-frame {
  width: 100%;
  height: 100%;
  border: none;
}

.image-preview {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #f5f7fa;
}

.preview-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.text-preview {
  width: 100%;
  height: 100%;
  padding: 20px;
  background-color: #f9f9f9;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  overflow: auto;
}

.text-content {
  white-space: pre-wrap;
  word-break: break-all;
  font-family: 'Courier New', monospace;
  margin: 0;
}

.loading-text {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  color: #909399;
}

.office-preview {
  width: 100%;
  height: 100%;
}

.pdf-preview {
  width: 100%;
  height: 100%;
}

.pdf-preview iframe {
  width: 100%;
  height: 100%;
  border: none;
}

.dev-info-container {
  padding: 20px;
}

.dev-info-actions {
  margin-top: 20px;
  text-align: right;
}

.dev-remarks {
  margin-top: 10px;
  color: #606266;
  white-space: pre-wrap;
  line-height: 1.6;
}

/* 操作按钮相关样式 */
.table-operation-buttons {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 4px 0;
}

.button-row {
  display: flex;
  justify-content: center;
}

.table-operation-buttons .el-button {
  margin: 0;
  padding: 4px 8px;
  min-width: 80px;
  white-space: nowrap;
}

.table-operation-buttons .el-icon {
  margin-right: 2px;
}

/* 响应式调整 */
@media screen and (max-width: 768px) {
  .button-row {
    flex-wrap: wrap;
  }

  .table-operation-buttons .el-button {
    width: auto;
  }
}

.el-upload__tip {
  font-size: 12px;
  color: #909399;
  margin-top: 5px;
}

.history-card-footer {
  margin-top: 12px;
  display: flex;
  justify-content: flex-end;
}

.download-actions {
  display: flex;
  gap: 12px;
}

.download-actions .el-button {
  padding: 4px 8px;
  font-size: 12px;
}
</style>